using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FlatRedBall;
using FlatRedBall.IO;
using FlatRedBall.Content.Scene;
using FlatRedBall.Input;
using Microsoft.Xna.Framework.Input;

using Xzipit.Utilities;

namespace Xzipit.Screens
{
    public class SplashScreen : Screen
    {
        enum SplashScreenState
        {
            None,
            NngFadingIn,
            NngShowingOpaque,
            NngFadingOut,
            GdcFadingIn,
            GdcShowingOpaque,
            GdcFadingOut,
            FrbFadingIn,
            FrbShowingOpaque,
            FrbFadingOut
        }

        SplashScreenState mState = SplashScreenState.None;

        Sprite _gdcLogo;
        Sprite _frbLogo;
        Sprite _nngLogo;

        public static string ScreenAfterSplash;
        CameraSave mOldCameraSetup;

        const double mTimeToShowOpaque = 3;
        double mTimeOpaqueShowingStarted = -1;
        const float mFadeTime = 0.2f; // number of seconds

        public SplashScreen()
            : base("SplashScreen")
        {

        }


        public override void Initialize(bool addToManagers)
        {
            base.Initialize(addToManagers);


            InitializeCamera();

            if (addToManagers)
            {
                AddToManagers();
            }
        }

        public override void AddToManagers()
        {
            _nngLogo = SpriteManager.AddSprite(@"Content/nng-logo");
            _nngLogo.PixelScale();

            _nngLogo.Alpha = 0.0f;

            _gdcLogo = SpriteManager.AddSprite(@"Content/gdc-logo");
            _gdcLogo.ScaleX = 256.0f;
            _gdcLogo.ScaleY = 256.0f;

            _gdcLogo.Alpha = 0.0f;

            _frbLogo = SpriteManager.AddSprite(@"Content/frb-logo");
            _frbLogo.ScaleX = 220.0f;
            _frbLogo.ScaleY = 90.0f;

            _frbLogo.Alpha = 0.0f;
        }

        private void InitializeCamera()
        {
            mOldCameraSetup = CameraSave.FromCamera(SpriteManager.Camera);

            SpriteManager.Camera.UsePixelCoordinates(false);
            SpriteManager.Camera.RotationX = 0;
            SpriteManager.Camera.RotationY = 0;
            SpriteManager.Camera.RotationZ = 0;

            SpriteManager.Camera.Position.X = 0;
            SpriteManager.Camera.Position.Y = 0;
            SpriteManager.Camera.Position.Z = 40;

            SpriteManager.Camera.Velocity.X = 0;
            SpriteManager.Camera.Velocity.Y = 0;
            SpriteManager.Camera.Velocity.Z = 0;

            // Zero-out any other properties here
        }

        public override void Activity(bool firstTimeCalled)
        {
            base.Activity(firstTimeCalled);

            if (firstTimeCalled)
            {

                if (string.IsNullOrEmpty(ScreenAfterSplash))
                {
                    throw new Exception("You need to set the ScreenAfterSplash " +
                        "before starting the SplashScreen");
                }
                _nngLogo.AlphaRate = 1 / mFadeTime;
                mState = SplashScreenState.NngFadingIn;
            }
            else
            {
                FadingActivity();
            }
        }

        private void FadingActivity()
        {
            switch (mState)
            {
                case SplashScreenState.NngFadingIn:
                    if (_nngLogo.Alpha > .99f || AnyInputPushed())
                    {
                        _nngLogo.Alpha = 1;
                        _nngLogo.AlphaRate = 0;

                        mTimeOpaqueShowingStarted = TimeManager.CurrentTime;
                        mState = SplashScreenState.NngShowingOpaque;

                    }
                    break;
                case SplashScreenState.NngShowingOpaque:

                    if (TimeManager.SecondsSince(mTimeOpaqueShowingStarted) > mTimeToShowOpaque ||
                        AnyInputPushed())
                    {
                        _nngLogo.AlphaRate = -1 / mFadeTime;
                        mState = SplashScreenState.NngFadingOut;
                    }


                    break;

                case SplashScreenState.NngFadingOut:

                    if (_nngLogo.Alpha < .01f || AnyInputPushed())
                    {

                        _nngLogo.Alpha = 0.0f;
                        _gdcLogo.AlphaRate = 1 / mFadeTime;


                        mState = SplashScreenState.GdcFadingIn;
                    }

                    break;
                case SplashScreenState.GdcFadingIn:
                    if (_gdcLogo.Alpha > .99f || AnyInputPushed())
                    {
                        _gdcLogo.Alpha = 1;
                        _gdcLogo.AlphaRate = 0;

                        mTimeOpaqueShowingStarted = TimeManager.CurrentTime;
                        mState = SplashScreenState.GdcShowingOpaque;

                    }
                    break;
                case SplashScreenState.GdcShowingOpaque:

                    if (TimeManager.SecondsSince(mTimeOpaqueShowingStarted) > mTimeToShowOpaque ||
                        AnyInputPushed())
                    {
                        _gdcLogo.AlphaRate = -1 / mFadeTime;
                        mState = SplashScreenState.GdcFadingOut;
                    }


                    break;

                case SplashScreenState.GdcFadingOut:

                    if (_gdcLogo.Alpha < .01f || AnyInputPushed())
                    {

                        _gdcLogo.Alpha = 0.0f;
                        _frbLogo.AlphaRate = 1 / mFadeTime;


                        mState = SplashScreenState.FrbFadingIn;
                    }

                    break;
                case SplashScreenState.FrbFadingIn:
                    if (_frbLogo.Alpha > .99f || AnyInputPushed())
                    {
                        _frbLogo.Alpha = 1;
                        _frbLogo.AlphaRate = 0;

                        mTimeOpaqueShowingStarted = TimeManager.CurrentTime;
                        mState = SplashScreenState.FrbShowingOpaque;

                    }
                    break;
                case SplashScreenState.FrbShowingOpaque:

                    if (TimeManager.SecondsSince(mTimeOpaqueShowingStarted) > mTimeToShowOpaque ||
                        AnyInputPushed())
                    {
                        _frbLogo.AlphaRate = -1 / mFadeTime;
                        mState = SplashScreenState.FrbFadingOut;
                    }


                    break;

                case SplashScreenState.FrbFadingOut:

                    if (_frbLogo.Alpha < .01f || AnyInputPushed())
                    {
                        IsActivityFinished = true;

                        NextScreen = ScreenAfterSplash;
                        if (GameProperties.Sound)
                        {
                            Microsoft.Xna.Framework.Media.MediaPlayer.Play(GameProperties.BgMusic);
                        }
                    }


                    break;
            }
        }

        public override void Destroy()
        {
            base.Destroy();

            mOldCameraSetup.SetCamera(SpriteManager.Camera);
            SpriteManager.RemoveSprite(_gdcLogo);
            SpriteManager.RemoveSprite(_frbLogo);
            SpriteManager.RemoveSprite(_nngLogo);
        }

        private bool AnyInputPushed()
        {
            foreach (Xbox360GamePad gamePad in InputManager.Xbox360GamePads)
            {
                if (gamePad.AnyButtonPushed())
                {
                    return true;
                }
            }

            if (InputManager.Keyboard.KeyPushed(Keys.Enter) ||
                InputManager.Keyboard.KeyPushed(Keys.Space) ||
                InputManager.Keyboard.KeyPushed(Keys.Escape))
            {
                return true;
            }

            if (InputManager.Mouse.AnyButtonPushed())
            {
                return true;
            }

            return false;
        }
    }
}